//
//  T3FMapPlatformView.swift
//  t3_map
//
//  Created by Cunhai Li on 2024/10/31.
//

import Foundation
import Flutter
import Bundle_Log
import CoreLocation
class T3FMapPlatformView<Registrar: FlutterPluginRegistrar>: NSObject, FlutterPlatformView {

    /// 地图初始化参数
    private var options: T3FMapOptions
    private let channelId: String
    private let registrar: Registrar

    /// 该地图的独立method channel
    let channel: FlutterMethodChannel
    let mapView: T3FMapView

    init(frame: CGRect, viewId: Int64, params: Any?, registrar: Registrar) {

        self.registrar = registrar

        /// options 初始化
        if let params = params, let map = params as? [String: Any] {

            if let mapType = map["mapType"] as? Int {

                if let type = T3FMapType(rawValue: mapType) {
                    options = T3FMapOptions(mapType: type, maxZoomLevel: 17, minZoomLevel: 3, showLocation: true)
                }
                else {
                    /// 默认使用高德地图
                    T3Log.error("地图初始化异常，mapType取值异常（2:高德,3:腾讯）实际值：\(mapType)，默认使用高德地图")
                    options = T3FMapOptions(mapType: .amap, maxZoomLevel: 17, minZoomLevel: 3, showLocation: true)
                }

            } else {
                /// 默认使用高德地图
                T3Log.error("地图初始化异常，未获取到mapType，默认使用高德地图")
                options = T3FMapOptions(mapType: .amap, maxZoomLevel: 17, minZoomLevel: 3, showLocation: true)
            }

            if let mapId = map["mapId"] as? String {
                channelId = mapId
            }
            else {
                assertionFailure("地图初始化失败，缺少mapId")
                T3Log.error("地图初始化异常，未获取到mapId，flutter无法向native进行通信")
                channelId = ""
            }

            //初始化中心点
            if let initialCameraPosition = map["initialCameraPosition"] as? [String : Any] {
                if let centerCoordinate = initialCameraPosition["centerCoordinate"] as? [String : Any] {
                    if let longitude = centerCoordinate["longitude"] as? Double,
                        let latitude = centerCoordinate["latitude"] as? Double {
                        options.initCameraPosition = T3FMapCameraPosition(centerCoordinate: CLLocationCoordinate2D(latitude: latitude, longitude: longitude))
                    }
                    else {
                        T3Log.error("地图初始化异常，未获取到centerCoordinate.longitude | latitude解析异常 ，地图中心点默认在天安门")
                    }
                }
                else {
                    T3Log.error("地图初始化异常，未获取到initialCameraPosition.centerCoordinate，地图中心点默认在天安门")
                }
            }
        }
        else {
            assertionFailure("地图初始化失败，缺少mapId")
            T3Log.error("地图初始化异常，构建参数传入有误")
            /// 默认使用高德地图
            options = T3FMapOptions(mapType: .amap, maxZoomLevel: 17, minZoomLevel: 3, showLocation: true)
            channelId = ""
        }

        /// 创建通信channel
        let channelName = "t3_map_flutter_map_\(channelId)"

        channel = FlutterMethodChannel(name: channelName, binaryMessenger: registrar.messenger())
        mapView = T3FMapManager.createMapView(frame: CGRect.zero, options: options)

        super.init()
        mapView.delegate = self
        self.setupMethodCallHandler()
    }

    deinit {
        print("")
    }

    func view() -> UIView {
        return mapView
    }

    enum T3FMapViewMethod: String {
        /// 设置地图的视图锚点
        case screenAnchor = "map#screenAnchor"
        /// 是否显示用户位置
        case showsUserLocation = "map#showsUserLocation"
        /// 定位用户位置的模式
        case userTrackingMode = "map#userTrackingMode"
        /// 当前位置再地图中是否可见
        case userLocationVisible = "map#userLocationVisible"
        /// 设置地图缩放级别
        case mapViewZoomLevel = "map#mapViewZoomLevel"
        /// 获取地图中心点
        case mapViewGetCenterCoordinate = "map#mapViewGetCenterCoordinate"
        /// 设置地图中心点
        case mapViewCenter = "map#mapViewCenter"
        /// 添加线段
        case addPolylines = "polylines#add"
        /// 更新线段
        case updatePolylines = "polylines#update"
        /// 移除线段
        case removePolylines = "polylines#remove"
        /// 在可视区域内显示Polyline
        case showPolylines = "polylines#show"
        /// 交换Polyline层级
        case exchangePolyline = "polyline#exchange"

        /// 标记物
        case addAnnotations = "annotation#add"
        case removeAnnotations = "annotation#remove"
        case showAnnotations = "annotation#show"
        case updateAnnotations = "annotation#update"

        /// 在可视区域内显示Polyline和Annotation
        case showPolylinesAndAnnotations = "map#showPolylinesAndAnnotations"
    }
    

    ///设置channel的方法监听
    func setupMethodCallHandler() {

        channel.setMethodCallHandler {[weak self] call, result in
            print("T3FMap: channelMsg = \(call.method)")
            guard let self = self else { return }
            guard let method = T3FMapViewMethod.init(rawValue: call.method) else {
                return
            }

            switch method {
            case .screenAnchor:
                screenAnchor(arguments: call.arguments)
            case .showsUserLocation:
                showsUserLocation(arguments: call.arguments)
            case .userTrackingMode:
                userTrackingMode(arguments: call.arguments)
            case .userLocationVisible:
                userLocationVisible(arguments: call.arguments, result:result)
            case .mapViewZoomLevel:
                setupMapViewZoomLevel(arguments: call.arguments)
            case .mapViewGetCenterCoordinate:
                getMapViewCenter(arguments: call.arguments, result: result)
            case .mapViewCenter:
                setupMapViewCenter(arguments: call.arguments)
            case .addPolylines:
                add(polyline: call.arguments)
            case .updatePolylines:
                update(polyline: call.arguments)
            case .removePolylines:
                remove(polyline: call.arguments)
            case .showPolylines:
                show(polylines: call.arguments)
            case .addAnnotations:
                add(annotations: call.arguments)
            case .removeAnnotations:
                remove(annotations: call.arguments)
            case .showAnnotations:
                show(annotations: call.arguments)
            case .updateAnnotations:
                update(annotation: call.arguments)
            case .showPolylinesAndAnnotations:
                showPolylinesAndAnnotations(arguments: call.arguments)
            case .exchangePolyline:
                exchange(polylines: call.arguments)
            }
        }
    }
}

extension T3FMapPlatformView {

    func screenAnchor(arguments: Any?) {
        do {
            let json = try T3FJsonUtil.toJson(arguments)

            if let offset = json["offset"] as? [String: Double] {
                if let x = offset["x"], let y = offset["y"] {
                    mapView.screenAnchor = CGPoint(x: x, y: y)
                }
                else {
                    T3Log.error("screenAnchor设置异常，缺少`x`|`y`字段，或者`x`|`y`字段类型错误")
                }
            }
            else {
                T3Log.error("screenAnchor设置异常，缺少`offset`字段，或者`offset`字段类型错误")
            }
        } catch (let error) {
            T3Log.error("screenAnchor异常：\(error.localizedDescription)")
        }
    }

    func showsUserLocation(arguments: Any?) {
        do {
            let json = try T3FJsonUtil.toJson(arguments)

            if let show = json["visible"] as? Bool {
                mapView.showsUserLocation = show
            }
            else {
                T3Log.error("showsUserLocation设置异常，缺少`visible`字段，或者`visible`字段类型错误")
            }
        } catch (let error) {
            T3Log.error("showsUserLocation异常：\(error.localizedDescription)")
        }
    }

    func userTrackingMode(arguments: Any?) {
        do {
            let json = try T3FJsonUtil.toJson(arguments)

            let animated = (json["animated"] as? Bool) ?? false

            if let modeValue = json["mode"] as? Int {

                if let mode = T3UserTrackingMode(rawValue: modeValue) {
                    mapView.setupUserTrackingMode(mode: mode, animated: animated)
                }
                else {
                    T3Log.error("userTrackingMode设置值错误，正确值[0,1,2]，实际为：\(modeValue)")
                }
            }
            else {
                T3Log.error("userTrackingMode设置异常，缺少`mode`字段，或者`mode`字段类型错误")
            }
        } catch (let error) {
            T3Log.error("userTrackingMode异常：\(error.localizedDescription)")
        }
    }

    func userLocationVisible(arguments: Any?, result: FlutterResult) {
        let json = ["visible": mapView.userLocationVisible]

        do {
            let string = try T3FJsonUtil.toString(json)
            result(string)
        } catch (let error) {
            T3Log.error("userLocationVisible异常：\(error.localizedDescription)")
        }
    }

    /// 设置地图缩放级别
    func setupMapViewZoomLevel(arguments: Any?) {
        do {
            let json = try T3FJsonUtil.toJson(arguments)

            let animated = (json["animated"] as? Bool) ?? false

            if let level = json["level"] as? Double {

                mapView.setupMapView(zoomLevel: level, animated: animated)
            }
            else {
                T3Log.error("setupMapViewZoomLevel设置异常，缺少`level`字段，或者`level`字段类型错误")
            }
        } catch (let error) {
            T3Log.error("setupMapViewZoomLevel异常：\(error.localizedDescription)")
        }
    }

    func getMapViewCenter(arguments: Any?, result: @escaping FlutterResult) {
        let json = [
            "longitude": mapView.centerCoordinate.longitude,
            "latitude": mapView.centerCoordinate.latitude
        ]
        result(try? T3FJsonUtil.toString(json))
    }

    /// 设置地图中心点
    func setupMapViewCenter(arguments: Any?) {

        do {
            let json = try T3FJsonUtil.toJson(arguments)

            let animated = (json["animated"] as? Bool) ?? false

            if let coordinate = json["coordinate"] as? [String: Double] {

                if let longitude = coordinate["longitude"], let latitude = coordinate["latitude"] {
                    mapView.setupCenter(CLLocationCoordinate2D(latitude: latitude, longitude: longitude), animated: animated)
                }
                else {
                    T3Log.error("setupMapViewCenter设置异常，缺少`longitude`| `latitude`字段，或者`longitude`| `latitude`字段类型错误")
                }
            }
            else {
                T3Log.error("setupMapViewCenter设置异常，缺少`coordinate`字段，或者`coordinate`字段类型错误")
            }
        } catch (let error) {
            T3Log.error("setupMapViewCenter异常：\(error.localizedDescription)")
        }
    }

    /// 在可视区域内显示Polyline和Annotation
    func showPolylinesAndAnnotations(arguments: Any?) {

        do {
            let json = try T3FJsonUtil.toJson(arguments)

            let animated = (json["animated"] as? Bool) ?? false

            var edgeInsets = UIEdgeInsets.zero
            if let edgeInsetsValue = json["edgeInsets"] as? [String: Double] {
                edgeInsets = T3FJsonUtil.edgeInsetsFrom(json: edgeInsetsValue) ?? .zero
            }

            let polylineOptions = toPolylineOptions(from: arguments)
            let annotationOptions = toAnnotationOptions(from: arguments)

            if let polylineOptions = polylineOptions,
                let annotationOptions = annotationOptions {
                
                mapView.show(polylines: polylineOptions, annotations: annotationOptions, edgePadding: edgeInsets, animated: animated)
            }
            else if let polylineOptions = polylineOptions {
                mapView.show(polylines: polylineOptions, edgePadding: edgeInsets, animated: animated)
            }
            else if let annotationOptions = annotationOptions {
                mapView.show(annotations: annotationOptions, edgePadding: edgeInsets, animated: animated)
            }
            else {
                T3Log.error("polyline + annotation异常：数据转换失败")
            }
        } catch (let error) {
            T3Log.error("showPolylinesAndAnnotations异常：\(error.localizedDescription)")
        }
    }
}
